<template>
	<view class="text-to-image-page">
		<!-- 提示词输入框 -->
		<view class="input-section">
			<text class="label">提示词</text>
			<textarea v-model="prompt" placeholder="请输入生成图片的描述" class="textarea-box" maxlength="1000"></textarea>
		</view>

		<!-- 照片风格选择 -->
		<view class="style-section">
			<text class="label">照片风格</text>
			<radio-group class="my-ration-group" @change="styleRadioChange">
				<view class="radio-item" v-for="style in styles" :key="style.value">
					<view class="radio-content">
						<radio :value="style.value" class="radio" :checked="selectedStyle === style.value">
							{{ style.label }}
						</radio>
					</view>
					<!-- 	<image :src="style.image" class="style-image" /> -->
				</view>
			</radio-group>
		</view>

		<!-- 图片比例选择 -->
		<view class="ratio-section">
			<text class="label">图片比例</text>
			<radio-group class="my-ration-group">
				<view class="radio-item" v-for="ratio in ratios" :key="ratio.value" @change="rationRadioChange">
					<radio :value="ratio.value" :checked="selectedRatio === ratio.value" class="radio">{{ ratio.label }}
					</radio>
				</view>
			</radio-group>
		</view>

		<!-- 模式选择 -->
		<view class="mode-section">
			<text class="label">模式</text>
			<radio-group class="my-ration-group">
				<view class="radio-item" v-for="mode in modes" :key="mode.value" @change="modeRadioChange">
					<radio :value="mode.value" :checked="selectedMode === mode.value" class="radio">{{ mode.label }}
					</radio>
				</view>
			</radio-group>
		</view>

		<!-- 生成图片按钮 -->
		<view class="generate-button-section">
			<button class="generate-button" @click="generateImage">生成图片</button>
		</view>

		<Loading ref="loadingRef" @close="loadingVisible = false" @show="loadingVisible=true" />


		<!-- 进度弹框 -->
		<view v-if="showProgressModal" class="progress-modal">
			<view class="progress-content">
				<!-- 显示的图片 -->
				<image :src="progressImage" class="progress-image" :style="progressImageStyle"></image>
				<!-- 进度条和百分比 -->
				<view class="progress-bar">
					<view class="progress" :style="{ width: progressPercentage + '%' }"></view>
				</view>
				<text class="progress-text">{{ progressPercentage }}%</text>

				<!-- 按钮部分 -->
				<view class="button-section">
					<button class="cancel-button" @click="cancelProgress">取消</button>
					<button class="confirm-button" @click="confirmProgress">确认</button>
				</view>
			</view>
		</view>
	</view>
</template>

<script lang="ts">
	import { defineComponent, ref, onMounted, onUnmounted, computed, watch } from 'vue';
	import { postTextToImage, getTextToImageQueue, getImageHistory, postInterruptRunningTask } from '@/api/openai';
	import globalConfig from '@/js/globals';
	import WebSocketService from '@/js/utils/websocket';
	import Loading from '@/components/CustomLoading'; // 根据你的项目结构调整路径
	import '@/styles/text2image.css';

	export default defineComponent({
		name: "Text2Image",
		components: {
			Loading
		},
		setup() {

			// 用户输入的提示词
			const prompt = ref<string>('');
			const loadingVisible = ref(false);
			const loadingRef = ref<InstanceType<typeof Loading> | null>(null); // 引用子组件
			// 照片风格选项，添加每个风格对应的图片路径
			const styles = ref([
				{ label: '3D可爱形象', value: 'CUTE_3D', image: '/static/styles/style1.jpeg' },
				{ label: '宫崎骏漫画', value: 'HAYAO_MIYAZAKI ', image: '/static/styles/style1.jpeg' },
				{ label: '赛博朋克', value: 'CYBERPUNK', image: '/static/styles/style1.jpeg' },
				{ label: '写实', value: 'REALISTIC', image: '/static/styles/style1.jpeg' },
				{ label: '胶片', value: 'FILM', image: '/static/styles/style1.jpeg' },
				{ label: '亚洲美女', value: 'ASIAN_GIRL', image: '/static/styles/style1.jpeg' }
			]);
			const styleRadioChange = (radio : any) => {
				selectedStyle.value = radio.detail.value;
			}
			// 图片比例选项
			const ratios = ref([
				{ label: '1:1', value: '512x512' },
				{ label: '16:9', value: '768x512' },
				{ label: '9:16', value: '512x768' },
				{ label: '4:3', value: '640x480' },
				{ label: '3:4', value: '480x640' }
			]);
			const rationRadioChange = (radio : any) => {
				console.log(radio.detail.value);
				selectedRatio.value = radio.detail.value;
			}
			// 新增的模式选择
			const modes = ref([
				{ label: '速度优先', value: '1' },
				{ label: '质量优先', value: '2' }
			]);
			const modeRadioChange = (radio : any) => {
				selectedMode.value = radio.detail.value;
			}

			const selectedStyle = ref(styles.value[0].value);
			// 使用 watch 监听 selectedStyle 的变化
			watch(selectedStyle, (newVal) => {
				console.log('selectedStyle changed to:', newVal);
			});

			const selectedRatio = ref(ratios.value[0].value);
			const selectedMode = ref(modes.value[0].value);
			//文生图接口返回的内容
			const promptId = ref('');
			const pendingNum = ref(0);
			const totalNum = ref(0);
			// 控制弹框显示
			const showProgressModal = ref(false);
			// 图片路径
			const progressImage = ref('/static/artworks/artwork1.png');  // 可替换为实际图片路径
			// 进度百分比
			const progressPercentage = ref(0);
			let currentWsService : WebSocketService = null; // 用于存储当前的 WebSocketService 实例
			const showImageInfoRef = ref(true);
			// 生成图片方法
			const generateImage = async () => {
				if (!prompt.value) {
					uni.showToast({
						title: '请先输入提示词',
						icon: 'none'
					});
					return;
				}
				// 在这里调用生成图片的 API，传递用户选择的参数
				const [width, height] = selectedRatio.value.split("x").map(Number);  // 转换为
				const params = {
					prompt: prompt.value,
					style: selectedStyle.value,
					width: width,
					height: height,
					clientId: globalConfig.clientId,
					//provider: globalConfig.text2ImageProvider,
					mode: selectedMode.value
				};
				console.log('生成图片参数：', params);
				console.log(loadingRef);
				loadingRef.value.showLoading('处理中,请稍候...');
				showImageInfoRef.value = true;
				const response = await postTextToImage(params);
				if (response.code == 200) {
					//立马开启websocket进行图片进度查看
					promptId.value = response.data.promptId;
					//查看图片生成状况的websocket 地址,服务器已经做好了封装,直接连接即可
					const wsUrl = response.data.wsUrl;
					connectWs(wsUrl);
				} else {
					loadingRef.value.closeLoading();
				}
				console.log("postTextToImage 请求结束,响应内容--->", response);

			};

			//连接websocket实时接收图片生成的进度
			const connectWs = async (wsUrl : string) => {
				// 如果已经存在一个 WebSocket 连接，先关闭它
				if (currentWsService) {
					currentWsService.disconnect(); // 停止现有的 WebSocket 连接
					currentWsService = null; // 清空引用
				}
				// const wsService = new WebSocketService('wss://notably-many-treefrog.ngrok-free.app/aigc/ws?clientId=' + clientId);
				const wsService = new WebSocketService(wsUrl);
				wsService.connect(); // 连接到 WebSocket 服务器
				progressPercentage.value = 0;
				// 设置接收消息的回调
				wsService.setOnMessageCallback((message) => {
					console.log('Received:', message);
					handleMessage(message);
				});

				// 设置错误处理的回调
				wsService.setOnErrorCallback((error) => {
					console.error('WebSocket Error:', error);
				});
				currentWsService = wsService;
			}

			// 假设 message 是接收到的 WebSocket 消息
			const handleMessage = async (message) => {
				//const parsedMessage = JSON.parse(message);

				if (message instanceof Blob) {
					handleImageBlob(message);
				}
				else {
					// 如果 message 不是 Blob 类型，假设它是 JSON 字符串
					try {
						const parsedMessage = JSON.parse(message);
						console.log('Parsed JSON:', parsedMessage);
						switch (parsedMessage.type) {
							case "progress":
								handleProgress(parsedMessage.data);
								break;
							case "executing":
								handleExecuting(parsedMessage.data);
								break;
							case "executed":
								handleExecuted(parsedMessage.data);
								break;
							case "execution_success":
								handleExecutionSuccess(parsedMessage.data);
								break;
							case "status":
								await handleStatus(parsedMessage.data);
								break;
							default:
								console.log("未知消息类型:", parsedMessage.type);
						}
						// 处理 JSON 数据
					} catch (error) {
						console.error('Error parsing JSON:', error);
					}
				}



			};

			const handleImageBlob = (blob : Blob) => {
				const reader = new FileReader();
				reader.onload = (e) => {
					// 转换 Blob 数据为 ArrayBuffer
					const arrayBuffer = e.target?.result as ArrayBuffer;
					// 跳过前8个字节元数据
					const imageData = arrayBuffer.slice(8);
					// 将 ArrayBuffer 的图像数据转换为 Blob
					const imageBlob = new Blob([imageData], { type: 'image/png' }); // 假设是 PNG 图像
					// 生成图片 URL 并设置到 imageUrl
					progressImage.value = URL.createObjectURL(imageBlob);
				};
				// 将 Blob 读取为 ArrayBuffer
				reader.readAsArrayBuffer(blob);
			}

			// 处理进度消息
			const handleProgress = (data) => {
				const { value, max, prompt_id } = data;
				console.log(`任务 ${prompt_id} 进度更新: ${value}/${max}`);
				loadingRef.value.closeLoading();
				// 计算进度条的 value（范围 1-100）
				const progressValue = Math.ceil((value / max) * 100);
				// 确保 progressValue 在 1 到 100 之间（防止意外超出范围）
				const clampedProgressValue = Math.max(1, Math.min(100, progressValue));
				progressPercentage.value = clampedProgressValue;
				//如果在处理过程中点击了确认，后续就不展示图片了，等一下次生成图片后会重制这个值
				if (showImageInfoRef.value) {
					showProgressModal.value = true;
				}
			};

			// 处理执行状态消息
			const handleExecuting = async (data) => {
				const { node, display_node, prompt_id } = data;
				console.log(`任务 ${prompt_id} 正在执行节点: ${display_node}`);
				// 可以更新执行状态的UI,当下一步没有节点了 && 并且采样器进度达到百分百,后续可能需要在调整
				if (!display_node && progressPercentage.value == 100) {
					console.log("所有任务完成....")
					//断开websocket连接
					currentWsService.disconnect();
					showImageInfo(promptId.value);
				}
			};

			// 处理执行完成消息
			const handleExecuted = (data) => {
				const { node, display_node, output, prompt_id } = data;
				console.log(`任务 ${prompt_id} 在节点 ${display_node} 执行完成，输出如下:`, output);
			};

			// 处理执行成功消息
			const handleExecutionSuccess = (data) => {
				const { prompt_id, timestamp } = data;
				console.log(`任务 ${prompt_id} 执行成功，时间戳: ${timestamp}`);
				// 更新状态或标记任务完成
			};

			// 处理状态消息
			const handleStatus = async (data) => {
				const queueRemaining = data.status.exec_info.queue_remaining;
				console.log(`当前队列剩余任务: ${queueRemaining}`);
				// 根据 queueRemaining 更新状态、UI 或进行其他操作
				if (queueRemaining > 0) {
					// 还有任务在处理, 查询下排队信息
					let params = {
						promptId: promptId.value
					};
					let textToImageQueueResponse = await getTextToImageQueue(params);
					if (textToImageQueueResponse.code == 200) {
						pendingNum.value = textToImageQueueResponse.data.pendingNum;
						totalNum.value = textToImageQueueResponse.data.totalNum;
						if (pendingNum.value != 0) {
							let content = "排队中，前面还有 " + pendingNum.value + " 个任务";
							loadingRef.value.showLoading(content);
						}
					}
				} else {
					// 所有任务都已完成，可以更新状态或UI
					console.log("所有任务已完成");
				}
			};

			// 展示最终生成的图片信息
			const showImageInfo = async (promptId : string) => {
				//查看生成的图片
				let params = {
					promptId: promptId
				};
				const response = await getImageHistory(params);
				console.log("getImageHistory结果--->", response);
				const images = response.data.images;
				//这里先默认展示第一张图,后续再考多张图展示
				if (images != null && images.length > 0) {
					progressImage.value = images[0].url;
				}

			};

			// 取消操作
			const cancelProgress = async () => {
				if (progressPercentage.value != 100) {
					const params = {
						promptId: promptId.value
					};
					const response = await postInterruptRunningTask(params);
				}
				showProgressModal.value = false;
				progressPercentage.value = 0;
				console.log('生成图片进度取消');
			};

			// 确认操作
			const confirmProgress = () => {
				showProgressModal.value = false;
				showImageInfoRef.value = false;
				if (currentWsService) {
					currentWsService.disconnect();
				}
				console.log('生成图片进度确认');
			};

			/**
			 * 动态计算图片的展示高度
			 */
			const progressImageStyle = computed(() => {
				const [widthRatio, heightRatio] = selectedRatio.value.split('x').map(Number);
				const aspectRatio = widthRatio / heightRatio;

				// 根据比例设置最大宽度和高度
				let width = '60vw'; // 默认宽度
				let height = `${60 / aspectRatio}vw`; // 根据宽高比计算高度

				// 限制最大高度
				const maxHeight = 70; // vh
				if (parseFloat(height) > maxHeight) {
					height = `${maxHeight}vh`;
					width = `${maxHeight * aspectRatio}vh`; // 根据新高度调整宽度
				}

				return {
					width,
					height,
					objectFit: 'contain', // 保持图片比例
				};
			});

			// 在 onMounted 中设置默认值
			onMounted(() => {

			});

			// 监听页面的卸载（关闭）事件
			onUnmounted(() => {
				console.log('组件已卸载，执行清理操作');
				// 如果有需要清理的操作，可以在这里进行，比如断开 WebSocket 连接、停止定时器等
				if (loadingRef.value) {
					loadingRef.value.closeLoading(); // 关闭加载框
				}
				if (currentWsService) {
					currentWsService.disconnect();
				}
			});

			return {
				prompt,
				styles,
				selectedStyle,
				ratios,
				selectedRatio,
				modes,
				selectedMode,
				generateImage,
				pendingNum,
				totalNum,
				showProgressModal,
				progressImage,
				progressPercentage,
				cancelProgress,
				confirmProgress,
				loadingVisible,
				loadingRef,
				styleRadioChange,
				progressImageStyle,
				modeRadioChange,
				rationRadioChange
			};
		}
	});
</script>